import { find_player } from '../../../player/player_class';

/**
 * 等级相关数据
 */
export const qualityData = [
    {
        level: 'R',
        nameColor: new GameRGBColor(0, 0, 1),
        meshScale: 1,
    },
    {
        level: 'SR',
        nameColor: new GameRGBColor(1, 0, 1),
        meshScale: 1.2,
    },
    {
        level: 'SSR',
        nameColor: new GameRGBColor(1, 1, 0),
        meshScale: 1.4,
    },
];

/**
 * 怪物基类
 *
 * 所有怪物类型都应该继承此类，该类提供了怪物的基本属性和方法。
 * 子类可以覆盖默认属性值并实现自己的特定行为。
 *
 * @example
 * ```typescript
 * class Goblin extends MonsterBase {
 *   constructor(entity: GameEntity) {
 *     super(entity);
 *     this.selftQuat = new GameQuaternion(0, 0, 0, 1);
 *     this.findRange = 10;
 *   }
 * }
 * ```
 */
class MonsterBase {
    /**
     * 游戏实体引用
     * 用于与游戏世界交互的实体对象
     */
    protected entity: GameEntity;

    /**
     * 旋转值
     * 控制怪物巡逻时的旋转角度
     */
    protected rot: number;

    /**
     * 旋转速度
     * 控制怪物巡逻时的旋转速度
     */
    protected rotSpeed: number;

    /**
     * 帧循环计数器
     */
    protected tick: number;

    /**
     * 旋转方向改变的时间点
     */
    protected rotTick: number;

    /**
     * 巡逻速度
     */
    protected walkSpeed: number;

    /**
     * 巡逻速度改变的时间点
     */
    protected speedTick: number;

    /**
     * 是否处于待机状态
     */
    protected inIdle: boolean;

    /**
     * 是否已死亡
     */
    protected beDead: boolean;

    /**
     * 模型对应的默认旋转四元数
     */
    protected selfQuat: GameQuaternion;

    /**
     * 模型大小
     */
    protected selfScale: number;

    /**
     * 寻敌范围
     */
    protected findRange: number;

    /**
     * 弃敌范围
     */
    protected loseRange: number;

    /**
     * 追踪范围区间
     * @description 当目标进入此范围时，怪物将开始追踪目标
     */
    protected traceStartRange: {
        /**
         * 追踪最大距离
         */
        max: number;
        /**
         * 追踪最小距离
         */
        min: number;
    };

    /**
     * 停止追踪范围区间
     * @description 当目标超出此范围时，怪物将放弃停止追踪目标
     */
    protected traceStopRange: {
        /**
         * 弃敌最大距离
         */
        max: number;
        /**
         * 弃敌最小距离
         */
        min: number;
    };

    /**
     * 追踪速度
     */
    protected traceSpeed: number;

    /**
     * 目标
     */
    protected target: GameEntity | null;

    /**
     * 是否正在追踪
     */
    protected tracing: boolean;

    /**
     * 是否能飞行
     */
    protected canFly: boolean;

    /**
     * 是否正在攻击
     */
    protected attacking: boolean;

    /**
     * 技能数量
     */
    protected skillCount: number;

    /**
     * 品质
     */
    protected quality: number;

    /**
     * 定时器引用
     */
    protected interval: number | null;

    /**
     * 构造函数
     *
     * 初始化怪物实例，设置默认属性值并调用初始化方法
     *
     * @param entity 游戏实体对象，用于与游戏世界进行交互
     * @example
     * ```typescript
     * const monster = new MonsterBase(entity);
     * ```
     */
    constructor(entity: GameEntity) {
        this.entity = entity;

        // 初始化基本属性
        this.rot = 0;
        this.rotSpeed = 1;
        this.walkSpeed = 0.1;

        //修改
        this.findRange = 100;
        this.loseRange = 200;

        this.traceStartRange = { max: 30, min: 0 };
        this.traceStopRange = { max: 30, min: 0 };

        this.traceSpeed = 0.1;
        this.target = null;
        this.tracing = false;
        this.interval = null;

        // 初始化状态
        this.beDead = false;
        this.attacking = false;
        this.canFly = false;
        this.inIdle = false;

        //修改
        this.skillCount = 1;

        this.quality = 0;

        // 初始化计时器
        this.tick = 0;
        this.rotTick = 0;
        this.speedTick = 0;

        // 初始化方向数据
        this.selfQuat = new GameQuaternion(0, 0, 0, 1);
        // 初始化模型大小
        this.selfScale = 0.0625;

        // 如果实体存在，初始化相关事件监听
        this.init();
        this.bindEvents();
        this.onInit();
    }

    /**
     * 初始化方法
     *
     * 在构造函数中自动调用，用于设置事件监听器或其他初始化逻辑。
     * 子类可以重写此方法以添加特定的初始化行为。
     */
    protected init() {
        if (this.entity) {
            this.entity.collides = true;
            this.entity.gravity = true;
            this.entity.addTag('monster');
            this.entity.enableDamage = true;

            this.entity.nameRadius = 15;
            this.entity.showEntityName = true;

            // 设置定时器执行帧更新
            this.interval = setInterval(() => {
                this.tick++;
                this.onTick();
            }, 60);

            // 监听死亡事件
            this.entity.onDie(({ attacker }) => {
                this.onDie(attacker);
            });
        }
    }

    bindEvents() {
        this.entity.onVoxelContact(({ voxel }) => {
            if (voxels.name(voxel) === 'plank_03') {
                this.entity.hurt(10);
            }
        });
    }

    /**
     * 初始化方法
     *
     * 默认空方法，子类可以覆盖此方法以添加特定的初始化逻辑。
     */
    onInit() {}

    /**
     * 帧更新方法
     *
     * 每帧调用，处理怪物的行为逻辑
     */
    protected onTick(): boolean {
        if (this.beDead) {
            return false;
        }

        let flag: boolean;

        // 如果有目标且目标在弃敌范围内，继续追踪
        if (
            this.target &&
            this.target?.destroyed &&
            this.target.position.distance(this.entity.position) <
                this.loseRange &&
            this.target.hp
        ) {
            this.moveToTarget(this.target.position);
            // 追踪逻辑
            if (this.tracing) {
                // // 已在追踪中，检查是否需要停止追踪
                // if (
                //     // 判断是否超出弃敌范围
                //     this.target.position.distance(this.entity.position) >
                //         this.traceStopRange.max ||
                //     this.target.position.distance(this.entity.position) <
                //         this.traceStopRange.min
                // ) {
                //     // 超出范围，停止追踪
                //     this.entity.velocity.copy(new GameVector3(0, 0, 0));
                //     this.tracing = false;
                // } else {
                //     // 继续追踪目标
                // }
            } else {
                if (
                    // 未在追踪中，检查是否需要开始追踪
                    this.target.position.distance(this.entity.position) <
                        this.traceStartRange.max &&
                    this.target.position.distance(this.entity.position) >
                        this.traceStartRange.min
                ) {
                    // 进入范围，开始追踪目标
                    this.tracing = true;
                } else {
                    // 未进入范围，不追踪
                    this.entity.velocity.copy(new GameVector3(0, 0, 0));
                }
            }

            // 尝试使用技能
            flag = true;
        } else {
            // 寻找附近的玩家
            const players = this.getNearbyPlayers(this.findRange);
            if (players.length > 0) {
                if (this.inIdle) {
                    this.inIdle = false;
                    this.turnToFight();
                }
                this.moveToTarget(players[0].position);
                this.target = players[0];
                this.tracing = true;

                // 如果有目标，则尝试使用技能
                flag = true;
            } else {
                if (!this.inIdle) {
                    this.inIdle = true;
                    this.turnToIdle();
                }
                this.animateNoAim();
                this.target = null;
                this.tracing = false;
                flag = false;
            }
        }
        if (flag) {
            this.useSkill();
        }
        return flag;
    }

    /**
     * 死亡处理方法
     *
     * @param attacker 攻击者实体
     */
    protected async onDie(attacker: GameEntity | null) {
        this.beDead = true;

        if (attacker && attacker.player && this.entity) {
            world.say(`${attacker.player.name} 打死了 ${this.entity.id}`);
        }

        this.entity.meshInvisible = true;
        this.entity.collides = false;
        this.entity.gravity = false;
        this.entity.fixed = true;
        this.entity.velocity.set(0, 0, 0);

        this.entity.particleRate = 100;
        this.entity.particleLifetime = 3;
        this.entity.particleSize = [3, 3, 3, 3, 3];
        this.entity.particleColor = [
            new GameRGBColor(0, 0, 0),
            new GameRGBColor(0, 0, 0),
            new GameRGBColor(0, 0, 0),
            new GameRGBColor(0, 0, 0),
            new GameRGBColor(0, 0, 0),
        ];
        this.entity.particleVelocitySpread = new GameVector3(1, 1, 1);
        this.entity.particleVelocity = new GameVector3(0, 3, 0);

        await sleep(1000);

        this.entity.hp = this.entity.maxHp;

        const ran = Math.random() * Math.PI * 2;

        this.entity.position.set(
            128 - Math.sin(ran) * 100,
            50,
            128 - Math.cos(ran) * 100
        );
        this.entity.particleRate = 0;
        this.entity.meshInvisible = false;
        this.entity.collides = true;
        this.entity.gravity = true;
        this.entity.fixed = false;

        this.beDead = false;
    }

    /**
     * 转换到待机状态
     */
    protected turnToIdle() {
        // 子类可以重写此方法
    }

    /**
     * 转换到战斗状态
     */
    protected turnToFight() {
        // 子类可以重写此方法
    }

    /**
     * 无目标时的动画表现
     */
    protected animateNoAim() {
        if (!this.entity) {
            return;
        }

        if (this.tick >= this.rotTick) {
            this.rotSpeed = Math.PI * (Math.random() - 0.5) * 0.25;
            this.rotTick = this.tick + this.randomRange(2, 4) * 16;
        }

        if (this.tick >= this.speedTick) {
            // this.walkSpeed = Math.random() * 0.3;
            this.speedTick = this.tick + this.randomRange(3, 5) * 16;
        }

        this.rot += this.rotSpeed * this.walkSpeed;
        const vx = Math.cos(this.rot) * this.walkSpeed;
        const vz = Math.sin(this.rot) * this.walkSpeed;

        if (this.entity) {
            this.entity.velocity.x = vx;
            this.entity.velocity.z = vz;
            this.entity.meshOrientation = this.selfQuat.rotateY(
                Math.atan2(vz, vx)
            );
        }
    }

    /**
     * 移动到目标位置
     *
     * @param pos 目标位置
     */
    protected moveToTarget(pos: GameVector3) {
        if (!this.entity) {
            return;
        }

        const vel = pos.sub(this.entity.position).normalize();
        if (!this.canFly) {
            vel.y = 0;
        }

        this.entity.velocity.x = vel.x * this.traceSpeed;
        //this.entity.velocity.y = vel.y * this.traceSpeed;
        this.entity.velocity.z = vel.z * this.traceSpeed;

        const ori = this.getOrientationByVector(this.selfQuat, vel);
        this.entity.meshOrientation = this.entity.meshOrientation.slerp(
            ori,
            0.24
        );

        // 地形检测
        const pos2 = new GameVector3(
            this.entity.position.x,
            this.entity.position.y - this.entity.bounds.y + 0.5,
            this.entity.position.z
        );
        const ray = world.raycast(pos2, vel, {
            maxDistance: 10,
            ignoreFluid: true,
            ignoreEntities: true,
        });

        if (ray.hit && ray.hitVoxel !== 0) {
            const pos = ray.voxelIndex;
            if (voxels.getVoxelId(pos.x, pos.y + 1, pos.z) === 0) {
                this.entity.velocity.y = 1;
            }
        }
    }

    /**
     * 获取附近的玩家列表
     *
     * @param range 搜索范围
     * @returns 玩家实体数组
     */
    protected getNearbyPlayers(range: number): GameEntity[] {
        //修改为使用find_player方法
        if (!this.entity) {
            return [];
        }

        let players = find_player<GameBounds3>(
            'Gamebound3',
            new GameBounds3(
                this.entity.position.sub(new GameVector3(range, range, range)),
                this.entity.position.add(new GameVector3(range, range, range))
            )
        );
        const pos = this.entity.position;
        players = players.filter(
            (e) => e.data.position.distance(pos) < range && e.data.hp
        );
        players.sort((a, b) => {
            return (
                a.data.position.distance(pos) - b.data.position.distance(pos)
            );
        });
        return players.map((e) => e.data.entitys.bound);
    }

    /**
     * 随机范围值
     *
     * @param start 起始值
     * @param end 结束值
     * @returns 随机值
     */
    protected randomRange(start: number, end: number): number {
        return start + (end - start) * Math.random();
    }

    /**
     * 根据向量计算方向
     *
     * @param quat 四元数
     * @param vector3 向量
     * @returns 计算后的四元数
     */
    protected getOrientationByVector(
        quat: GameQuaternion,
        vector3: GameVector3
    ): GameQuaternion {
        const src = vector3;
        const dx = src.x;
        const dy = src.y;
        const dz = src.z;
        const dist = Math.sqrt(dx * dx + dz * dz);
        const rotx = Math.atan2(dy, dist);
        return quat.rotateX(rotx).rotateY(Math.atan2(dz, dx));
    }

    /**
     * 使用技能
     */
    protected async useSkill() {
        if (this.attacking || this.skillCount <= 0) {
            return;
        }

        // 随机选择技能
        const randomIndex = Math.floor(this.randomRange(0, this.skillCount));

        const skillName = `skill_${randomIndex}` as keyof this;
        if (typeof this[skillName] === 'function') {
            this.attacking = true;

            // 调用技能方法
            await this[skillName]();

            this.attacking = false;
        }
    }

    /**
     * 设置品质
     */
    public setQuality(quality: number) {
        this.quality = quality;
        this.entity.nameColor = qualityData[quality].nameColor;
        this.entity.meshScale.set(
            this.selfScale * qualityData[quality].meshScale,
            this.selfScale * qualityData[quality].meshScale,
            this.selfScale * qualityData[quality].meshScale
        );

        this.entity.position.y += 1;
    }

    /**
     * 杀死附近的玩家/对范围内的玩家进行操作
     *
     * @param range 搜索范围
     * @param action 行为
     */
    killRange(range: number, action: (entity: GameEntity) => void): void {
        if (!this.entity) {
            return;
        }

        const players = this.getNearbyPlayers(range);
        players.forEach((entity) => action(entity));
    }
}

// 导出怪物基类
export default MonsterBase;
